#include "EditorMeshPageViewModel.h"

#include "Scene/Scene.h"
#include "Scene/StaticMeshComponent.h"
#include "Scene/DirectionalLightComponent.h"
#include "Scene/CameraComponent.h"
#include "Scene/InputComponent.h"

#include "Material/MaterialSubsystem.h"

#include "Asset/EngineDefaultPackage.h"
#include "Asset/EditorDefaultPackage.h"

#include "Scene/TickComponent.h"

REditorMeshPageViewModel::~REditorMeshPageViewModel()
{
    if(MeshScene)
    {
        MeshScene->EndPlay();
    }
}

void REditorMeshPageViewModel::BindModel(TSharedObjectPtr<REditorPageModel> InModel)
{
    Super::BindModel(InModel);
    Model = InModel;

    Icon= REditorDefaultPackage::Get()->GetIcon(U"MeshIcon");

    MeshScene = NewObject<RScene>();
    {
        auto Light=MeshScene->NewNode<RSceneNode>();
        Light->SetNodeName(U"DirectionalLight");
        Light->SetWorldPosition(SVec3(0,0,0)); //any where is ok
        Light->SetWorldRotation(SQuat::FromEuler(SVec3(CMathBase::DegreeToRadian(-45.f),0,0)));
        {
            auto LightComponent=Light->CreateAndAddComponent<RDirectionalLightComponent>();
        }

        float FloorSize= Model->Mesh->GetBoundingSphereRadius() * 5;
        auto GreyFloor=MeshScene->NewNode<RSceneNode>();
        GreyFloor->SetNodeName(U"GreyFloor");
        GreyFloor->SetWorldPosition(SVec3(0,0,-1));
        GreyFloor->SetScale(SVec3(FloorSize,FloorSize,1));
        {
            auto MeshComponent=GreyFloor->CreateAndAddComponent<RStaticMeshComponent>();
            MeshComponent->SetStaticMesh(REngineDefaultPackage::Get()->GetCubeMesh());
            MeshComponent->SetMaterials({REngineDefaultPackage::Get()->GetDefaultMaterial()});

        }

        auto MeshNode=MeshScene->NewNode<RSceneNode>();
        MeshNode->SetNodeName(U"Mesh");
        MeshNode->SetWorldPosition(SVec3(0,0,0));
        MeshNode->SetWorldRotation(SQuat::FromEuler(SVec3(0,0,0)));
        auto PreviewMeshComponent=MeshNode->CreateAndAddComponent<RStaticMeshComponent>();
        {
            PreviewMeshComponent->SetStaticMesh(Model->Mesh);
            PreviewMeshComponent->SetMaterials(Model->Mesh->DefaultMaterials);
        }
        RStaticMeshComponentWeakPtr MeshComponentWeak=PreviewMeshComponent;
        auto UpdateMaterialComponent=MeshNode->CreateAndAddComponent<RTickComponent>();
        {
            UpdateMaterialComponent->TickFunction.BindLambda(
                [this,MeshComponentWeak](float DeltaSeconds)
                {
                    MeshComponentWeak->SetMaterials(
                        Model->Mesh->DefaultMaterials
                    );
                }

            );
        }

        MeshScene->BeginPlay();    
    }

    ViewDistanceToMesh=Model->Mesh->GetBoundingSphereRadius() * 2;
}

TSharedObjectPtr<RTexture2D> REditorMeshPageViewModel::GetIcon() const
{
    return Icon;
}

CString REditorMeshPageViewModel::GetTitle() const
{
    return Model->Mesh->GetNodeName();
}

float REditorMeshPageViewModel::GetViewDistanceToMesh()
{
    return ViewDistanceToMesh;
}

float REditorMeshPageViewModel::GetMeshHeight() const
{
    return Model->Mesh->GetBoundingSphereRadius() * 2;
}

TSharedObjectPtr<RStaticMesh> REditorMeshPageViewModel::GetMesh() const
{
    return Model->Mesh;
}

TSharedObjectPtr<RScene> REditorMeshPageViewModel::GetMeshScene() const
{
    return MeshScene;
}
